﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.IO;
using System.Reflection;
using AMStudio.Script;
using System.Data;

namespace AMStudio.Common
{
    public static class RuntimeDB
    {
        private static Hashtable rtdbTags = new Hashtable();
        public static Hashtable RTDBTags
        {
            get { return RuntimeDB.rtdbTags; }
        }

        public static SortedDictionary<string, MachineInformationItem> Errors;
        public static SortedDictionary<string, MachineInformationItem> Conditions;
        public static SortedDictionary<string, MachineInformationItem> Errors_CN;
        public static SortedDictionary<string, MachineInformationItem> Conditions_CN;

        public static Hashtable UITagCollection = new Hashtable();
        public static Hashtable UITagGroupCollection = new Hashtable();

        public static void Init(string compiledFileName)
        {
            try
            {
                string modulePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetModules()[0].FullyQualifiedName);
                FileInfo IODescriptionFile = new FileInfo(compiledFileName + ".dll");
                FileInfo XLSLoaderFile = new FileInfo("cfg\\IO_Config.xls");
                if (IODescriptionFile.LastWriteTime < XLSLoaderFile.LastWriteTime)
                {
                    RefrenceTagFileCreator IOCreator = new RefrenceTagFileCreator("AMStudio.Common");
                    IOCreator.AddClass("RTDBTags");
                    InitRTDBTags(IOCreator["RTDBTags"]);
                    IOCreator.CompileCSharpCode(compiledFileName + ".dll", "/keyfile:IPTE_SH_Public.snk /doc:" + compiledFileName + ".xml", new string[] { "RuntimeDB.dll" }, true);
                }
                else
                {
                    InitRTDBTags(null);
                }
                InitErrorsConditions();
            }
            catch (Exception ex)
            {
                throw new Exception("RuntimeDB Init Error:" + ex.Message);
            }
        }
        public static void SetLanguage(string culture)
        {
            try
            {
                InitErrorsConditions();
            }
            catch (Exception ex)
            {
                throw new Exception("RuntimeDB SetLanguage Error");
                throw ex;
            }
        }

        public static void InitRTDBTags(RefrenceTagGroupCreator myClass)
        {
            RuntimeTagDAL db = new RuntimeTagDAL();
            IList<RuntimeItem> list = db.SelectAllMapper();
            if (list == null)
            {
                return;
            }
            for (int i = 0; i < list.Count; i++)
            {
                RuntimeItem roughItem = list[i];
                if (string.IsNullOrEmpty(roughItem.DataType.Trim()))
                    continue;
                try
                {
                    RuntimeItem item;
                    if (roughItem.Length > 1)
                    {
                        switch (roughItem.DataType.Trim())
                        {
                            case "Discrete":
                                item = new RuntimeTag<System.Boolean[]>();
                                break;
                            case "Integer":
                                item = new RuntimeTag<System.Int32[]>();
                                break;
                            case "Real":
                                item = new RuntimeTag<System.Single[]>();
                                break;
                            default:
                                throw new Exception("can't support this type");
                        }
                    }
                    else
                    {
                        switch (roughItem.DataType.Trim())
                        {
                            case "Discrete":
                                item = new RuntimeTag<System.Boolean>();
                                break;
                            case "Integer":
                                item = new RuntimeTag<System.Int32>();
                                break;
                            case "Real":
                                item = new RuntimeTag<System.Single>();
                                break;
                            default:
                                throw new Exception("can't support this type");
                        }
                    }
                    item.Name = roughItem.Name.Trim();
                    item.DataType = roughItem.DataType.Trim();
                    item.Length = roughItem.Length;
                    item.TagID = roughItem.TagID.Trim();
                    item.Position = roughItem.Position;
                    item.RelateTag = roughItem.RelateTag.Trim();
                    item.DeviceTag = roughItem.DeviceTag.Trim();
                    item.Action = roughItem.Action.Trim();
                    item.Comments = roughItem.Comments.Trim();
                    item.Module = roughItem.Module.Trim();
                    rtdbTags.Add(item.Name, item);

                    string itemDescription = "TagID=" + item.TagID
                        + ",position=" + item.Position + ",relateTag=" + item.RelateTag + ",deviceTag=" + item.DeviceTag
                        + ",action=" + item.Action + ",comments=" + item.Comments;

                    if (myClass == null)
                        continue;
                    if (item.Length > 1)
                    {
                        switch (item.DataType)
                        {
                            case "Discrete":
                                myClass.AddRefrence(item.Name, "RuntimeTag", itemDescription, "System.Boolean[]");
                                break;
                            case "Integer":
                                myClass.AddRefrence(item.Name, "RuntimeTag", itemDescription, "System.Int32[]");
                                break;
                            case "Real":
                                myClass.AddRefrence(item.Name, "RuntimeTag", itemDescription, "System.Single[]");
                                break;
                            default:
                                throw new Exception("can't support this type");
                        }
                    }
                    else
                    {
                        switch (item.DataType)
                        {
                            case "Discrete":
                                myClass.AddRefrence(item.Name, "RuntimeTag", itemDescription, "System.Boolean");
                                break;
                            case "Integer":
                                myClass.AddRefrence(item.Name, "RuntimeTag", itemDescription, "System.Int32");
                                break;
                            case "Real":
                                myClass.AddRefrence(item.Name, "RuntimeTag", itemDescription, "System.Single");
                                break;
                            default:
                                throw new Exception("can't support this type");
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw new Exception("RTDBTags Init Error:" + roughItem.Name + ex.Message);
                }
            }
        }
        public static void InitErrorsConditions()
        {
            RuntimeTagDAL db = new RuntimeTagDAL();
            Errors = new SortedDictionary<string,MachineInformationItem>(db.GetAllErrors());     
            Conditions = new SortedDictionary<string,MachineInformationItem>(db.GetAllConditions());
            Errors_CN = new SortedDictionary<string, MachineInformationItem>(db.GetAllErrors_CN());
            Conditions_CN = new SortedDictionary<string, MachineInformationItem>(db.GetAllConditions_CN());


            RemoveInsignificantItems(Errors);
            RemoveInsignificantItems(Conditions);
            RemoveInsignificantItems(Errors_CN);
            RemoveInsignificantItems(Conditions_CN);
        }

        public static void RemoveInsignificantItems(SortedDictionary<string, MachineInformationItem> SDItems)
        {

            try
            {
                List<string> list = new List<string>();
                foreach (KeyValuePair<string, MachineInformationItem> it in SDItems)
                {
                    MachineInformationItem item = it.Value;
                    if (item.Address == "" || item.Address == "None")
                        continue;

                    string[] Strlist;
                    Strlist = item.Message.Split(':');
                    if (Strlist.Length < 2 || Strlist.Length > 2 && Strlist[2].Trim() == "")
                        list.Add(item.Code);
                }

                foreach (string it in list)
                {
                    SDItems.Remove(it);
                }

            }
            catch
            {

            }
        }

        public static T GetTag<T>(string tagName) where T : class
        {
            T returnVal = rtdbTags[tagName] as T;
            //if (returnVal == null)
            //{
            //    throw new Exception("Tag " + tagName + " not exist,please check IOConfig file");
            //}
            return returnVal;
        }
        public static StringValueList<T> GetTagGroup<T>(string module, string comments) where T : RuntimeItem
        {
            StringValueList<T> res = new StringValueList<T>();
            foreach (DictionaryEntry d in rtdbTags)
            {
                T item = d.Value as T;
                if (item == null)
                    continue;
                if ((item.Module.IndexOf(module) >= 0) && (item.Comments.IndexOf(comments) >= 0))
                    res.Add((T)item);
            }
            res.Sort(ComparePosition);
            return res;
        }
        public static StringValueList<T> GetTagGroup<T>(string module) where T : RuntimeItem
        {
            StringValueList<T> res = new StringValueList<T>();

            foreach (DictionaryEntry d in rtdbTags)
            {
                T item = d.Value as T;
                if (item == null)
                    continue;
                if ((item.Module.IndexOf(module) >= 0))
                    res.Add((T)item);
            }
            res.Sort(ComparePosition);
            return res;
        }
        private static int ComparePosition(RuntimeItem c1, RuntimeItem c2)
        {
            if (c1.Position > c2.Position)
            {
                return 1;
            }
            else if (c1.Position == c2.Position)
            {
                return 0;
            }
            else
            {
                return -1;
            }
        }
        public static bool ExistTag<T>(string tagName) where T : class
        {
            T returnVal = rtdbTags[tagName] as T;
            if (returnVal == null)
            {
                return false;
            }
            return true;
        }
    }
}
